﻿Imports System.IO
Imports NewHeaderSystems.Archive.Types

Public Class TradeSuiteProcessor
    Inherits BaseProcessor

    Private Const fld_SecurityID As String = "Common Sec I"
    Private Const fld_Side As String = "Side"
    Private Const fld_Units As String = "Share Qty"
    Private Const fld_Currency As String = "Intl Curre"
    Private Const fld_BkrDlrName As String = "Bkr Dlr Name"
    Private Const fld_PricePerShare As String = "Price Per Share"
    Private Const fld_TradeDate As String = "Trade Date"
    Private Const fld_SettlementDate As String = "Settlement"
    Private Const fld_Commission As String = "Commission"
    Private Const fld_Fee As String = "Fee"
    Private Const fld_NetAmount As String = "Net Amount"
    Private Const fld_ClrBkrNum As String = "Clr Bkr #"
    Private Const fld_DTCControlNumber As String = "DTC Contr"
    Private Const fld_RetrieveSubtype As String = "Retrieve Subtype"
    Private Const fld_DTCStatus As String = "DTC Status"
    Private Const fld_ConfirmType As String = "Confirm Type"
    Private Const fld_BkrDlrNum As String = "Bkr Dlr #"
    Private Const fld_BkrDlrBIC As String = "Bkr Dlr BIC"
    Private Const fld_BkrDlrAccountNum As String = "Bkr Dlr Acct #"
    Private Const fld_ControlNum As String = "Bkr Dlr Conf"
    Private Const fld_OriginalBkrControlNum As String = "Orig Bkr Con"
    Private Const fld_ClrBkrName As String = "Clr Bkr Name"
    Private Const fld_InstitutionID As String = "Institutio"
    Private Const fld_InstitutionName As String = "Inst Name"
    Private Const fld_AgtNum As String = "Agt #"
    Private Const fld_AgtName As String = "Agt Name"
    Private Const fld_AgtAccountNum As String = "Agt Int Acct #"
    Private Const fld_ClrAgtNum As String = "Clr Agt #"
    Private Const fld_ClrAgtName As String = "Clr Agt Name"
    Private Const fld_Market As String = "Market"
    Private Const fld_AccountType As String = "Account Ty"
    Private Const fld_SettlementCode As String = "Settlement Code"
    Private Const fld_SettlementLocation As String = "Settlement Loc"
    Private Const fld_Role As String = "Role"
    Private Const fld_SecurityIndicator As String = "Common Sec"
    Private Const fld_ExpSecurityType As String = "Exp Sec Type"
    Private Const fld_SecurityDescription As String = "Security Desc"
    Private Const fld_NetPrice As String = "Net Price"
    Private Const fld_Principal As String = "Principal"
    Private Const fld_AccruedInterest As String = "Accrued Interes"
    Private Const fld_OtherCharges As String = "Other Charges"
    Private Const fld_SpecialInstr1 As String = "Special Instr 1"
    Private Const fld_SpecialInstr2 As String = "Special Instr 2"
    Private Const fld_SpecialInstr3 As String = "Special Instr 3"
    Private Const fld_SpecialInstr4 As String = "Special Instr 4"
    Private Const fld_SpecialInstr5 As String = "Special Instr 5"
    Private Const fld_InterestedParty1 As String = "Int Pty 1"
    Private Const fld_InterestedParty1Name As String = "Int Pty 1 Name"
    Private Const fld_ActivityDate As String = "Activity Da"
    Private Const fld_ActivityTime As String = "Activity Ti"
    Private Const fld_ProcessDate As String = "Process Dat"
    Private Const fld_ProcessTime As String = "Process Tim"
    Private Const fld_AccrBegin As String = "Accr Begin"
    Private Const fld_AccrEnd As String = "Accr End Da"
    Private Const fld_EligIndicator As String = "Ineligible Reason 1"
    Private Const fld_CancelIndicator As String = "Cancel Reason"

    ' parses the trade suite format
    Public Function Process(ByVal sourceFilePath As String, ByVal userID As Integer) As Integer
        BackgroundReporter.MessagePrefix = Path.GetFileName(sourceFilePath)
        Dim reader As New StreamReader(New FileStream(sourceFilePath, FileMode.Open, FileAccess.Read))
        Dim header As Dictionary(Of String, Integer) = ParseHeader(reader.ReadLine)
        Dim line = reader.ReadLine
        Dim confirmsList As New List(Of TradeSuite)
        Do While Not line Is Nothing
            Dim tradeSuite As TradeSuite = ParseTSLine(line, header)
            BackgroundReporter.ReportProgress(tradeSuite.ToString())
            AplProcessor.FindMatch(tradeSuite)
            confirmsList.Add(tradeSuite)
            line = reader.ReadLine
        Loop
        reader.Close()
        BackgroundReporter.ReportProgress("Saving confirms...")
        Return Save(confirmsList, userID, sourceFilePath)
    End Function

    ' parses a TradeSuite confirm file
    Private Function ParseTSLine(ByVal dataLine As String, ByVal header As Dictionary(Of String, Integer)) As TradeSuite
        Dim TSRec As New TradeSuite
        Dim line() As String

        ' fix dataLine
        line = CleanAndSplitLine(dataLine)

        TSRec.Source = "TS"
        TSRec.AccountID = "" ' needs to be looked up
        TSRec.TickerSymbol = "" ' needs to be looked up

        TSRec.SecurityID = GetFieldValue(header, line, fld_SecurityID)
        TSRec.Side = GetFieldValue(header, line, fld_Side)
        TSRec.Units = GetFieldValue(header, line, fld_Units)
        TSRec.Currency = GetFieldValue(header, line, fld_Currency)
        TSRec.BkrDlrName = GetFieldValue(header, line, fld_BkrDlrName)
        TSRec.PricePerShare = GetFieldValue(header, line, fld_PricePerShare)
        TSRec.TradeDate = GetFieldValue(header, line, fld_TradeDate)
        TSRec.SettlementDate = GetFieldValue(header, line, fld_SettlementDate)
        TSRec.Commission = GetFieldValue(header, line, fld_Commission)
        TSRec.Fee = GetFieldValue(header, line, fld_Fee)
        TSRec.NetAmount = GetFieldValue(header, line, fld_NetAmount)
        TSRec.ClrBkrNum = StripLeadingZeros(GetFieldValue(header, line, fld_ClrBkrNum))
        TSRec.ControlNum = GetFieldValue(header, line, fld_ControlNum)
        TSRec.RetrieveSubtype = GetFieldValue(header, line, fld_RetrieveSubtype)
        TSRec.DTCStatus = GetFieldValue(header, line, fld_DTCStatus)
        TSRec.ConfirmType = GetFieldValue(header, line, fld_ConfirmType)
        TSRec.BkrDlrNum = StripLeadingZeros(GetFieldValue(header, line, fld_BkrDlrNum))
        TSRec.BkrDlrBIC = GetFieldValue(header, line, fld_BkrDlrBIC)
        TSRec.BkrDlrAccountNum = GetFieldValue(header, line, fld_BkrDlrAccountNum)
        TSRec.DTCControlNumber = GetFieldValue(header, line, fld_DTCControlNumber)
        TSRec.OriginalBkrControlNum = GetFieldValue(header, line, fld_OriginalBkrControlNum)
        TSRec.ClrBkrName = GetFieldValue(header, line, fld_ClrBkrName)
        TSRec.InstitutionID = StripLeadingZeros(GetFieldValue(header, line, fld_InstitutionID))
        TSRec.InstitutionName = GetFieldValue(header, line, fld_InstitutionName)
        TSRec.AgtNum = StripLeadingZeros(GetFieldValue(header, line, fld_AgtNum))
        TSRec.AgtName = GetFieldValue(header, line, fld_AgtName)
        TSRec.AgtAccountNum = GetFieldValue(header, line, fld_AgtAccountNum)
        TSRec.ClrAgtNum = StripLeadingZeros(GetFieldValue(header, line, fld_ClrAgtNum))
        TSRec.ClrAgtName = GetFieldValue(header, line, fld_ClrAgtName)
        TSRec.Market = GetFieldValue(header, line, fld_Market)
        TSRec.AccountType = GetFieldValue(header, line, fld_AccountType)
        TSRec.SettlementCode = GetFieldValue(header, line, fld_SettlementCode)
        TSRec.SettlementLocation = GetFieldValue(header, line, fld_SettlementLocation)
        TSRec.Role = GetFieldValue(header, line, fld_Role)
        TSRec.SecurityIndicator = GetFieldValue(header, line, fld_SecurityIndicator)
        TSRec.ExpSecurityType = GetFieldValue(header, line, fld_ExpSecurityType)
        TSRec.SecurityDescription = GetFieldValue(header, line, fld_SecurityDescription)
        TSRec.SecurityDescription2 = ""
        TSRec.SecurityDescription3 = ""
        TSRec.NetPrice = GetFieldValue(header, line, fld_NetPrice)
        TSRec.Principal = GetFieldValue(header, line, fld_Principal)
        TSRec.Reg_Shp = ""   ' APL only
        TSRec.Taxes = ""     ' APL only
        TSRec.AccruedInterest = GetFieldValue(header, line, fld_AccruedInterest)
        TSRec.OtherCharges = GetFieldValue(header, line, fld_OtherCharges)
        TSRec.SpecialInstr1 = GetFieldValue(header, line, fld_SpecialInstr1)
        TSRec.SpecialInstr2 = GetFieldValue(header, line, fld_SpecialInstr2)
        TSRec.SpecialInstr3 = GetFieldValue(header, line, fld_SpecialInstr3)
        TSRec.SpecialInstr4 = GetFieldValue(header, line, fld_SpecialInstr4)
        TSRec.SpecialInstr5 = GetFieldValue(header, line, fld_SpecialInstr5)
        TSRec.InterestedParty1 = GetFieldValue(header, line, fld_InterestedParty1)
        TSRec.InterestedParty1Name = GetFieldValue(header, line, fld_InterestedParty1Name)
        TSRec.InterestedParty2 = "" ' APL only
        TSRec.InterestedParty2Name = ""  ' APL only
        TSRec.ActivityDate = GetFieldValue(header, line, fld_ActivityDate)
        TSRec.ActivityTime = GetFieldValue(header, line, fld_ActivityTime)
        TSRec.ProcessDate = GetFieldValue(header, line, fld_ProcessDate)
        TSRec.ProcessTime = GetFieldValue(header, line, fld_ProcessTime)
        TSRec.AccrBegin = GetFieldValue(header, line, fld_AccrBegin)
        TSRec.AccrEnd = GetFieldValue(header, line, fld_AccrEnd)

        TSRec.HeadingLine = ""
        TSRec.AffirmStatus = ""
        TSRec.EligIndicator = GetFieldValue(header, line, fld_EligIndicator)
        TSRec.CancelIndicator = GetFieldValue(header, line, fld_CancelIndicator)

        ' build headerline and affirmstatus                               
        If String.IsNullOrEmpty(TSRec.EligIndicator) Then
            TSRec.HeadingLine = "DTC ELIGIBLE"
        Else
            TSRec.HeadingLine = "DTC INELIGIBLE: " & TSRec.EligIndicator
        End If
        If Not String.IsNullOrEmpty(TSRec.CancelIndicator) Then
            TSRec.HeadingLine = TSRec.HeadingLine & " CANCEL"
        End If
        TSRec.HeadingLine = TSRec.HeadingLine & Space(50 - Len(TSRec.HeadingLine)) & "CONFIRMATION"
        TSRec.AffirmStatus = "AFFIRM BY 12:00 PM EST"

        Return TSRec
    End Function

    ''' <summary>
    ''' Gets the field value.
    ''' </summary>
    ''' <param name="header">The header.</param>
    ''' <param name="line">The line.</param>
    ''' <param name="strField">The STR field.</param>
    ''' <returns></returns>
    Private Function GetFieldValue(ByVal header As Dictionary(Of String, Integer), ByVal line As String(), ByVal strField As String) As String

        If header.ContainsKey(strField) Then
            Return line(header(strField)).Trim()
        Else
            Return String.Empty
        End If
    End Function

    Private Function StripLeadingZeros(ByVal value As String) As String
        Return value.TrimStart("0"c)
    End Function

    ''' <summary>
    ''' Cleans ands splits the line.
    ''' </summary>
    ''' <param name="line">The line.</param>
    ''' <returns></returns>
    Private Function CleanAndSplitLine(ByVal line As String) As String()
        line = line.Replace(Chr(34) & "," & Chr(34), Chr(34) & "|" & Chr(34))
        line = line.Replace(Chr(34), "")
        Return Split(line, "|")
    End Function

    ''' <summary>
    ''' Parses the header.
    ''' </summary>
    ''' <param name="line">The line.</param>
    ''' <returns></returns>
    Private Function ParseHeader(ByVal line As String) As Dictionary(Of String, Integer)
        Dim header As New Dictionary(Of String, Integer)
        Dim splitLine As String() = CleanAndSplitLine(line)
        For index As Integer = 0 To splitLine.Length - 1
            header.Add(splitLine(index).Trim(), index)
        Next
        Return header
    End Function
End Class
